package com.siecom.module;

import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;

import com.ivsign.android.IDCReader.IDCReadInterface;
import com.pos.api.Sys;
import com.pos.emvcore.EmvCore;
import com.pos.emvcore.beans.AidList;
import com.pos.emvcore.beans.AppList;
import com.pos.emvcore.beans.CAPubKey;
import com.siecom.bean.LoadLogBean;
import com.siecom.constconfig.ErrorDefine;
import com.siecom.bean.BankCardInfoBean;
import com.siecom.bean.TradeLogBean;
import com.siecom.hostservice.MainActivity;
import com.siecom.tool.ByteTool;
import com.siecom.tool.LogUtil;
import com.siecom.tool.StringUtil;
import com.siecom.tool.Timer;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by zhq on 2016/8/19.
 */
public class FinancialRunnable extends ModuleRunnable {

    public static final String TAG = FinancialRunnable.class.getSimpleName();
    public static FinancialModule financialModule = FinancialModule.getInstance();

    private EmvCore mEmvCore = null;

    public enum Action {

        READ_MSR,
        READ_IC_CARD_NO,
        READ_PIC_CARD_NO,
        AUTO_READ_CARD_NO,
        READ_IC_INFO,
        READ_PIC_INFO,
        AUTO_READ_CARD_INFO,
        READ_PIC_LOG,
        READ_IC_LOG,
        READ_PIC_LOAD,
        READ_IC_LOAD,
        AUTO_READ_LOAD,
        AUTO_READ_LOG,
        ARPCANDSCRIPT

    }

    private Action type;
    private EmvOptions emvOptions;

    private int cardType;
    private String ARPC;
    private String ScriptStr;


    private String[] wantTags = null;


    public void stopRun() {
        this.runFlag = false;
        financialModule.setStopRun(true);
    }

    public FinancialRunnable(Action type, EmvOptions emvOptions, final DeviceCallback callback, final String[] wantTags, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
        this.emvOptions = emvOptions;
        this.wantTags = wantTags;
        this.mEmvCore = MainActivity.getEmvCore();
    }


    public FinancialRunnable(Action type, EmvOptions emvOptions, final DeviceCallback callback, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = type;
        this.emvOptions = emvOptions;

        this.mEmvCore = MainActivity.getEmvCore();
    }

    public FinancialRunnable(int cardType, String ARPC, String ScriptStr, final DeviceCallback callback, final int timeOutMs, final boolean isOnMain) {
        this.callback = callback;
        this.timeOutMs = timeOutMs;
        this.isOnMain = isOnMain;
        this.type = Action.ARPCANDSCRIPT;
        this.cardType = cardType;
        this.ARPC = ARPC;
        this.ScriptStr = ScriptStr;
        this.mEmvCore = MainActivity.getEmvCore();
    }

    @Override
    public void run() {
        synchronized (this) {
//            financialModule.flush();
//            initEmv();
            switch (type) {
                case READ_MSR:
                    readMsr();
                    break;
                case READ_IC_CARD_NO:
                    financialModule.icLightOn();
                    readIcCardNo();
                    financialModule.icLightOff();
                    break;
                case READ_PIC_CARD_NO:

                    readPiccCardNo();
                    break;
                case AUTO_READ_CARD_NO:
//                    financialModule.msrLightOn();
//                    financialModule.icLightOn();
                    autoReadCardNo();
//                    financialModule.msrLightOff();
//                    financialModule.icLightOff();
                    break;
                case READ_IC_INFO:
                    readIcCardInfo();
                    break;
                case READ_PIC_INFO:
                    readPiccInfo();
                    break;

                case READ_IC_LOG:
                    readIcLog();
                    break;
                case READ_PIC_LOG:
                    readPicLog();
                    break;
                case AUTO_READ_LOG:
                    autoReadCardLog();
                    break;


                case READ_IC_LOAD:
                    readIcLoadLog();
                    break;

                case READ_PIC_LOAD:
                    readPicLoadLog();
                    break;


                case AUTO_READ_CARD_INFO:
                    autoReadCardInfo();
                    break;
                case AUTO_READ_LOAD:
                    financialModule.icLightOn();
                    autoReadCardLoad();
                    financialModule.msrLightOff();
                    break;

                case ARPCANDSCRIPT:
//                    ARPCExecuteScript(cardType, ARPC, ScriptStr);
                    ARPCExecuteScript(cardType,0,0);
                    break;
            }
            isFinish = true;
            Log.e(TAG, "COMPLETED");
        }
    }

    public int initEmv() {

        if (financialModule.EmvLib_Init() == 0) {
            Log.e("EmvLib_Init", "ok");
            return 0;
        }
        return -1;
    }

    public int ARPCExecuteScript(int ICType, String ARPC, String ScriptStr) {

        byte[] RspCode = null;
        byte[] AuthCode = "123456".getBytes();
        int AuthCodeLen = 0;
        byte ucResult = 0;
        byte[] IAuthData = new byte[8];
        byte[] Script = null;
        int IAuthDataLen = 0;
        int ScriptLen = 0;
        byte[] Result = new byte[1024];
        int[] RetLen = new int[1];
        int ret = -1;
//        final String arpc = "910A2501EEC5A3FDBF563030";//91开头，脚本是72开头
//        final String script = "7251860F04DA9F790A000000000000A4B17D6D860F04DA9F770A0000001000008C09E6BF862D04DC010C2870229F61123433313232313139383830373136313231589F6201105F2006C5CBB0D8D3EEA168BB5A";

        try {
            int nIndex = ARPC.indexOf("91");
            if (nIndex != -1) {
                String substr = ARPC.substring(nIndex + 2,
                        nIndex + 4);
                IAuthDataLen = Integer.parseInt(substr, 16);
                Log.e(TAG, "IAuthDataLen = " + IAuthDataLen);
                IAuthData = StringUtil.hexStringToBytes(ARPC.substring(nIndex + 4, nIndex + 4 + IAuthDataLen * 2));
                Log.e(TAG, "IAuthData = " + ByteTool.bytearrayToHexString(IAuthData, IAuthDataLen));
                RspCode = StringUtil.hexStringToBytes(ARPC.substring(nIndex + 4 + IAuthDataLen * 2 - 4, nIndex + 4 + IAuthDataLen * 2));
                Log.e(TAG, "RspCode = " + ByteTool.bytearrayToHexString(RspCode, 2));
            }
            nIndex = ScriptStr.indexOf("72");
            if (nIndex != -1) {
                String substr = ScriptStr.substring(nIndex + 2,
                        nIndex + 4);
                ScriptLen = Integer.parseInt(substr, 16) + 2;
                Log.e(TAG, "ScriptLen = " + ScriptLen);
                Script = StringUtil.hexStringToBytes(ScriptStr.substring(nIndex, nIndex + ScriptLen * 2));
                Log.e(TAG, "Script = " + ByteTool.bytearrayToHexString(Script, ScriptLen));
            } else {
                Script = new byte[0];
            }
            if (ICType == 0x00)
                ret = financialModule.EmvLib_ProcTransComplete(ucResult, RspCode, AuthCode, AuthCodeLen, IAuthData, IAuthDataLen, Script, ScriptLen);
            else if (ICType == 0x02)
                ret = financialModule.EmvLib_ProcCLTransComplete((byte) 0, RspCode, AuthCode, AuthCodeLen);
            else {
                deliverError(ErrorDefine.CARD_TYPE_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.CARD_TYPE_ERR));
                return ret;
            }
            if (ret != 0) {
                Log.e(TAG, "EmvLib_ProcCLTransComplete/EmvLib_ProcTransComplete: ret = " + ret);
                deliverError(ErrorDefine.PBOC_COMPLETE, ErrorDefine.getErrorDescribe(ErrorDefine.PBOC_COMPLETE));
                return ret;
            }
            byte[] ScriptResult = new byte[0];
            if(nIndex!=-1) {
                if (ICType == 0x00) {
                    ret = financialModule.EmvLib_GetScriptResult(Result, RetLen);
                    if (ret != 0) {
                        Log.e(TAG, "EmvLib_GetScriptResult: ret = " + ret);
                        deliverError(ErrorDefine.GET_SCRIPT_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_SCRIPT_ERR));
                        return ret;
                    }
                }
                ScriptResult = new byte[RetLen[0]];

                System.arraycopy(Result, 0, ScriptResult, 0, ScriptResult.length);
            }
            String[] tags = {"9F26"}; //应用密文（AC）  长度8

            byte[] dataOut = new byte[1024];
            int[] len1 = new int[1];
            ret = financialModule.EmvLib_GetTags(tags, dataOut, len1);

            byte[] out = new byte[len1[0]];
            System.arraycopy(dataOut, 0, out, 0, len1[0]);
            if (ret == 0) {
                Bundle bundle = new Bundle();
                bundle.putInt("result", ret);
                bundle.putString("ScriptResult", ByteTool.byte2hex(ScriptResult));
                bundle.putString("TC", ByteTool.byte2hex(out));
                deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            } else {
                Bundle bundle = new Bundle();
                bundle.putInt("code", ret);
                bundle.putString("ScriptResult", ByteTool.byte2hex(ScriptResult));
                bundle.putString("TC", ByteTool.byte2hex(out));
                bundle.putString("message", "unknow script or arpc err");
                deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
            }
        } catch (Exception e) {
            e.printStackTrace();
            deliverError(e.hashCode(), e.getMessage());

        } finally {
            if (ICType == 0x00)
                financialModule.libIccClose((byte) 0x00);
            else if (ICType == 0x02)
                financialModule.libPiccClose();

            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }
        return ret;

    }


    public int ARPCExecuteScript(int iCType, int authAmt, int cashbackAmt){
        try {
            int ret = -1;
            if(iCType == 0){
                ret = tranProcess(authAmt,cashbackAmt);
                Bundle bundle = new Bundle();
                bundle.putInt("result", ret);
//                bundle.putString("ScriptResult", ByteTool.byte2hex(ScriptResult));
//                bundle.putString("TC", ByteTool.byte2hex(out));
                if(ret == 0){
                    deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                }else {
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                }


            }else if(iCType == 2){
                ret = clTranProcess(authAmt,cashbackAmt);
                Bundle bundle = new Bundle();
                bundle.putInt("result", ret);
//                bundle.putString("ScriptResult", ByteTool.byte2hex(ScriptResult));
//                bundle.putString("TC", ByteTool.byte2hex(out));
                if(ret == 0){
                    deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
                }else {
                    deliverResult(callback, DeviceInterface.Result.ERROR, bundle, isOnMain);
                }
            }
        }catch (Exception e){
            LogUtil.e(TAG,e.getMessage());

        }finally {
            if(iCType == 0){
                MainActivity.getmMainIcc().DLL_IccClose((byte) 0);
            }else if(iCType == 1){
                MainActivity.getmMainPicc().DLL_PiccClose();
            }
        }

        return 0;
    }
    //接触式
    private int tranProcess(int authAmt, int cashbackAmt) {
        int iRet = -1;

        MainActivity.miTransCount++;

        AppList[] appList = new AppList[16];
        int[] listSize = new int[1];

        for (int i = 0; i < 16; i++) {
            appList[i] = new AppList();
        }

        System.out.println("tranProcess---EmvLibBuildCandidateList");
        iRet = mEmvCore.EmvLibBuildCandidateList(0, appList, listSize);
        LogUtil.e(TAG,"EmvLibBuildCandidateList iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibSelectApp(0);
        LogUtil.e(TAG,"EmvLibSelectApp 0 iRet =" + iRet);
        if (0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibInitAppProcessing(0, MainActivity.miTransCount, authAmt, cashbackAmt);
        LogUtil.e(TAG,"EmvLibInitAppProcessing iRet =" + iRet);
        if (0 != iRet &&
                ErrorDefine.RET_ERR_APPSEL != iRet)
            return iRet;

        while (ErrorDefine.RET_ERR_APPSEL == iRet) {
            iRet = mEmvCore.EmvLibGetNewCandidateList(appList, listSize);
            LogUtil.e(TAG,"EmvLibGetNewCandidateList iRet =" + iRet);
            if (0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibSelectApp(0);
            LogUtil.e(TAG,"EmvLibSelectApp iRet =" + iRet);
            if (0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibInitAppProcessing(0, 1, authAmt, cashbackAmt);
            LogUtil.e(TAG,"EmvLibInitAppProcessing iRet =" + iRet);
            if (0 != iRet &&
                    ErrorDefine.RET_ERR_APPSEL != iRet)
                return iRet;
        }

        iRet = mEmvCore.EmvLibReadAppData();
        LogUtil.e(TAG,"EmvLibReadAppData iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibCheckExceptionPan();
        LogUtil.e(TAG,"EmvLibCheckExceptionPan iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibTerminalRiskManage();
        LogUtil.e(TAG,"EmvLibTerminalRiskManage iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibOfflineAuth();
        LogUtil.e(TAG,"EmvLibOfflineAuth iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibProcessingRestrictions();
        LogUtil.e(TAG,"EmvLibProcessingRestrictions iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibCardholderVerification();
        LogUtil.e(TAG,"EmvLibCardholderVerification iRet =" + iRet);
        if (0 != iRet)
            return iRet;

        int acType = 0;
        acType = mEmvCore.EmvLibTerminalActionAnalysis();
        LogUtil.e(TAG,"EmvLibBuildCandidateList acType =" + acType);
        if (ErrorDefine.ACTYPE_AAC == acType) {
            iRet = mEmvCore.EmvLib1stGenAC(acType);
            LogUtil.e(TAG,"EmvLib1stGenAC iRet =" + iRet);
            return iRet;
        } else {

            iRet = mEmvCore.EmvLib1stGenAC(acType);
            LogUtil.e(TAG,"EmvLib1stGenAC iRet =" + iRet);
            if (iRet <= 0)
                return iRet;

            acType = iRet;

            //online process

            //online flow
            byte[] authData = new byte[]{0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x2A, 0x2B};
            if (authData.length > 0) {
                mEmvCore.EmvLibHostAuth(authData, authData.length);
                LogUtil.e(TAG,"EmvLibHostAuth iRet =" + iRet);
            }


            byte[] scriptBuf = new byte[]{0x71, 0x12, (byte) 0x9F, 0x18, 0x04, 0x11, 0x22, 0x33, 0x44, (byte) 0x86, 0x09, (byte) 0x84, 0x24, 0x00, 0x00, 0x04, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD};
            if (scriptBuf.length > 0) {
                mEmvCore.EmvLibScriptProcessing((byte) 0x71, scriptBuf, scriptBuf.length);
            }

            byte[] rspCode = new byte[]{0x30, 0x30};
            byte[] authCode = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
            iRet = mEmvCore.EmvLib2stGenAC(acType, ErrorDefine.ONLINE_RET_APPROVE, rspCode, authCode, authCode.length);
            LogUtil.e(TAG,"EmvLib2stGenAC iRet =" + iRet);
//            scriptBuf = new byte[]{0x72, 0x12, (byte) 0x9F, 0x18, 0x04, 0x11, 0x22, 0x33, 0x44, (byte) 0x86, 0x09, (byte) 0x84, 0x24, 0x00, 0x00, 0x04, (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD};
//            if (scriptBuf.length > 0) {
//                mEmvCore.EmvLibScriptProcessing((byte) 0x72, scriptBuf, scriptBuf.length);
//            }

            //	return 0;
            return iRet;
        }
    }
    //非接
    private int clTranProcess(int authAmt, int cashbackAmt)
    {
        int iRet = -1;

        AppList[] appList = new AppList[16];
        int[] listSize = new int[1];

        for(int i = 0; i < 16; i++)
        {
            appList[i] = new AppList();
        }

        iRet = mEmvCore.QpbocLibPreProcess(authAmt, cashbackAmt);
        System.out.println("clTranProcess---QpbocLibPreProcess iRet: " + iRet);
        if(0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibBuildCandidateList(1, appList, listSize);
        if(0 != iRet)
            return iRet;

        iRet = mEmvCore.EmvLibSelectApp(0);
        if(0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibInitAppProcessing(1, MainActivity.miTransCount, authAmt, cashbackAmt);
        if(0 != iRet &&
                ErrorDefine.RET_ERR_APPSEL != iRet)
            return iRet;

        while(ErrorDefine.RET_ERR_APPSEL == iRet)
        {
            iRet = mEmvCore.EmvLibGetNewCandidateList(appList, listSize);
            if(0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibSelectApp(0);
            if(0 != iRet)
                return iRet;

            iRet = mEmvCore.EmvLibInitAppProcessing(0, 1, authAmt, cashbackAmt);
            if(0 != iRet &&
                    ErrorDefine.RET_ERR_APPSEL != iRet)
                return iRet;
        }

        iRet = mEmvCore.EmvLibReadAppData();
        LogUtil.e(TAG,"EmvLibReadAppData ret == " + iRet);
        if(0 != iRet)
            return iRet;


        iRet = mEmvCore.EmvLibOfflineAuth();
        LogUtil.e(TAG,"EmvLibOfflineAuth ret == " + iRet);
        if(0 != iRet)
            return iRet;

        iRet = mEmvCore.QpbocLibTerminalActionAnalysis();
        LogUtil.e(TAG,"QpbocLibTerminalActionAnalysis ret == " + iRet);
        if(ErrorDefine.ACTYPE_ARQC != iRet)
            return iRet;

        //online process
        //
        byte[] rspCode = new byte[]{0x30, 0x30};
        byte[] authCode = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
        iRet = mEmvCore.QpbocLibCompleteOnlineTrans(ErrorDefine.ONLINE_RET_APPROVE, rspCode, authCode, authCode.length);
        LogUtil.e(TAG,"QpbocLibCompleteOnlineTrans ret == " + iRet);
        return iRet;
    }

    /**
     * 自动识别卡读取交易明细记录
     */
    public void autoReadCardLog() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        if(res==1){
//            financialModule.PowerOff();
//            SystemClock.sleep(1000);
//            financialModule.PowerOn();
//            SystemClock.sleep(3000);
//            financialModule.EmvLib_Init();
            res = openModule();
        }
        Log.e(TAG, "openModule:" + res);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                    break;
                }
            }
            SystemClock.sleep(100);
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {

                byte[] atr = new byte[20];
                res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                if (res != 0) {
                    continue;
                }
                if (getA108PLog((byte) 0x00) == 0) {

                    break;
                }
            }


            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLog((byte) 0x02) == 0) {

                    MainActivity.getmMainPicc().DLL_PiccClose();
                    break;
                }
            }

            SystemClock.sleep(100);

        }
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 自动识别卡读取圈存记录
     */
    public void autoReadCardLoad() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        if(res==1){

            res = openModule();
        }
        Log.e(TAG, "openModule:" + res);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                    break;
                }
            }
            SystemClock.sleep(100);
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {

                byte[] atr = new byte[20];
                res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                if (res != 0) {
                    continue;
                }
                if (getA108PLoadLog((byte) 0x00) == 0) {

                    break;
                }
            }


            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLoadLog((byte) 0x01) == 0) {

                    MainActivity.getmMainPicc().DLL_PiccClose();
                    break;
                }
            }

            SystemClock.sleep(100);

        }
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    /**
     * 自动识别卡类型
     */
    public void autoReadCardInfo() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
//        res = MainActivity.getmMainPicc().DLL_PiccOpen();
         res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
        LogUtil.e(TAG,"autoReadCardInfo picc open res" + res);
        res = MainActivity.getMainMcr().DLL_McrOpen();
        if(res==1){
//            financialModule.PowerOff();
//            SystemClock.sleep(1000);
//            financialModule.PowerOn();
//            SystemClock.sleep(3000);
//            financialModule.EmvLib_Init();
//            res = openModule();
            res = IDCReadInterface.DLL_IDOpen(1); //NFC 上电;
            res = MainActivity.getMainMcr().DLL_McrOpen();
        }
        Log.e(TAG, "autoReadCardInfo openModule:" + res);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                        break;
                    }
                }
                SystemClock.sleep(100);
                if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {


                    LogUtil.e(TAG,"autoReadCardInfo 读IC卡 检查卡成功");
                    byte[] atr = new byte[20];
                    res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                    LogUtil.e(TAG,"ICC open res=" + res);

                    if (res == 1) {
//                        financialModule.PowerOff();
//                        SystemClock.sleep(1000);
//                        financialModule.PowerOn();
//                        SystemClock.sleep(3000);
//
//                        financialModule.EmvLib_Init();
                        continue;
                    }
                    if (res != 0) {
                        continue;
                    }
                    if (transBeforeOnline((byte) 0x00) == 0) {

                        break;
                    }
                }


                byte[] cardType = new byte[2];
                byte[] serialNo = new byte[100];
                if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardType, serialNo) == 0) {
                    if (transBeforeOnline((byte) 0x02) == 0) {
//                        MainActivity.getmMainPicc().DLL_PiccClose();

                        break;
                    }
                }

                SystemClock.sleep(100);
                if (MainActivity.getMainMcr().DLL_McrCheck() == 0) {
                    if (mcrRead()) {
                        MainActivity.getMainMcr().DLL_McrClose();
                        break;
                    }
                }
                SystemClock.sleep(100);

            }
        }finally {
//            IDCReadInterface.DLL_IDClose(); // 身份证NFC模块下电
//            closeModule();
            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }

    }

    public void readPicLoadLog() {
        Timer tm = openPicc();
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.PIC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.PIC_CRAD_TIMEOUT));
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLoadLog((byte) 0x01) == 0) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        MainActivity.getmMainPicc().DLL_PiccClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    public void readIcLoadLog() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {
                byte[] atr = new byte[20];
                int res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                if (res == 1) {
//                    financialModule.PowerOff();
//                    SystemClock.sleep(1000);
//                    financialModule.PowerOn();
//                    SystemClock.sleep(3000);
//
//                    financialModule.EmvLib_Init();
                    continue;
                }
                if (res != 0) {
                    continue;
                }
                if (getA108PLoadLog((byte) 0x00) == 0) {

                    break;
                }

            }
            SystemClock.sleep(200);
        }
        MainActivity.getmMainIcc().DLL_IccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);


    }

    public void readPicLog() {
        Timer tm = openPicc();
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.PIC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.PIC_CRAD_TIMEOUT));
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardtype, snbuf) == 0) {
                if (getA108PLog((byte) 0x01) == 0) {

                    break;
                }
            }
            SystemClock.sleep(100);
        }
        MainActivity.getmMainPicc().DLL_PiccClose(); //关闭非接卡
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 读IC交易明细
     */
    public void readIcLog() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }
            if (MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00) == 0) {
                LogUtil.e(TAG,"已检测到 IC卡");
                byte[] atr = new byte[20];
                int res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                LogUtil.e(TAG," IC卡DLL_IccOpen=" + res);
                if (res != 0) {
                    continue;
                }
                if (getA108PLog((byte) 0x00) == 0) {
                    break;
                }

            }
            SystemClock.sleep(200);
        }
        MainActivity.getmMainIcc().DLL_IccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    public int getLoadLog(int cardType) {
        int ret = -1;
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");// 设置日期格式
        String time = df.format(new Date());
        ret = financialModule.setDateTime(ByteTool.hexStr2Bytes(time));
        if (ret != 0) {
            deliverError(ErrorDefine.SET_TIME_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_TIME_ERR));
            return -1;
        }
        ret = setEMVParam();
        if (ret != 0) {
            deliverError(ErrorDefine.SET_EMVPARAM_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_EMVPARAM_ERR));
            return -2;
        }
        byte[] tlog = new byte[1024];
        int[] num = new int[1];
        int res = -1;
        if (cardType == 0x00) {
            res = financialModule.EmvLib_GetLoadLog((byte) 0x00, tlog, num);
        } else if (cardType == 0x02) {
            res = financialModule.EmvLib_GetLoadLog((byte) 0x01, tlog, num);

        }
        Log.e("EmvLib_GetLog:", res + "--");
        if (res != 0) {
            deliverError(ErrorDefine.GET_LOE_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_LOE_ERR));
            return res;
        }
        List<LoadLogBean> list = parseLoadLog(tlog);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<LoadLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
        return res;
    }

    /**
     * 读圈存交易日志
     * @param cardType
     * @return
     */
    public int getA108PLoadLog(int cardType){
        int ret = -1;
        ret=  mEmvCore.EmvLibInitReadLog(cardType);
        LogUtil.e(TAG,"EmvLibInitReadLog ret ="  + ret);
        if(ret != 0){
            deliverError(ErrorDefine.EMV_INIT_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_INIT_ERR));
            return ret;
        }
//        //标签对应数据：交易日期3，交易时间3，授权金额6，其他金额6，终端国家代码2，交易货币代码2，商户名称20，交易类型1，应用交易计数器 2
//        int[] tags = new int[]{0x9A,0x9F21,0x9F02,0x9F03,0x9F1A,0x5F2A,0x9F4E,0x9C,0x9F36};
//        int[] dlen = new int[]{3,   3,     6,     6,     2,     2,     20,     1,   2    };
        //标签对应数据：授权金额6，其他金额6，交易货币代码2，交易类型1，终端国家代码2，应用交易计数器 2,交易日期3，交易时间3，商户名称20，
        int[] tags = new int[]{0x9F02,0x9F03,0x5F2A,0x9C,0x9F1A,0x9F36,0x9A,0x9F21,0x9F4E};
//        int[] dlen = new int[]{6,     6,      2,    1,    2,     2 ,    3,   3,     20    };
        byte[] allData = new byte[1024];
        for(int i=1;i<11;i++){
            ret = mEmvCore.EmvLibReadLoadLogRd(i);
            LogUtil.e(TAG,"--" + i +  "--请求读取一条圈存交易日志 ret ="  + ret);
            if (ret == 0){ //读取成功 之后再去取数据
                byte[] dataOut = new byte[20];
                int[] outLen = new int[1];
                int len = 0;
                for(int j=0; j<tags.length; j++){
                    ret = mEmvCore.EmvLibReadLoadLogItem(tags[j], dataOut,outLen);
                    LogUtil.e(TAG,"outLen--" + outLen[0] + "--"  + String.format("%02x", tags[j]) + "--Log读取成功：" + ByteTool.byte2hex(dataOut));
                    if (ret == 0){ //取数据成功
                        allData[0] = (byte) i;
                        int desPOs = 1 + len + (i-1)*45;
                        LogUtil.e(TAG,  "len ="  + len +  "------j==" + j + "-------desPOs==" + desPOs);
                        System.arraycopy(dataOut,0,allData,desPOs,outLen[0]);
                        len += outLen[0];
                        LogUtil.e(TAG,ByteTool.byte2hex(allData));
                    }
                }

            }else {
                if(i == 1 && ret == -17){//没有交易日志
                    LogUtil.e(TAG,"没有交易日志");
//                    deliverError(ErrorDefine.RET_ERR_NORECORD, ErrorDefine.getErrorDescribe(ErrorDefine.RET_ERR_NORECORD));
                }
                break;
            }

        }
        List<TradeLogBean> list = parseLog(allData);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;
    }

    public int getA108PLog(int cardType){
        int ret = -1;
        ret=  mEmvCore.EmvLibInitReadLog(cardType);
        LogUtil.e(TAG,"EmvLibInitReadLog ret ="  + ret);
        if(ret != 0){
            deliverError(ErrorDefine.EMV_INIT_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_INIT_ERR));
            return ret;
        }
//        //标签对应数据：交易日期3，交易时间3，授权金额6，其他金额6，终端国家代码2，交易货币代码2，商户名称20，交易类型1，应用交易计数器 2
//        int[] tags = new int[]{0x9A,0x9F21,0x9F02,0x9F03,0x9F1A,0x5F2A,0x9F4E,0x9C,0x9F36};
//        int[] dlen = new int[]{3,   3,     6,     6,     2,     2,     20,     1,   2    };
        //标签对应数据：授权金额6，其他金额6，交易货币代码2，交易类型1，终端国家代码2，应用交易计数器 2,交易日期3，交易时间3，商户名称20，
        int[] tags = new int[]{0x9F02,0x9F03,0x5F2A,0x9C,0x9F1A,0x9F36,0x9A,0x9F21,0x9F4E};
//        int[] dlen = new int[]{6,     6,      2,    1,    2,     2 ,    3,   3,     20    };
        byte[] allData = new byte[1024];
        for(int i=1;i<11;i++){
            ret = mEmvCore.EmvLibReadTxLogRd(i);
            LogUtil.e(TAG,"--" + i +  "--请求读取一条交易日志 ret ="  + ret);
            if (ret == 0){ //读取成功 之后再去取数据
                byte[] dataOut = new byte[20];
                int[] outLen = new int[1];
                int len = 0;
                for(int j=0; j<tags.length; j++){
                    ret = mEmvCore.EmvLibReadTxLogItem(tags[j], dataOut,outLen);
//                    LogUtil.e(TAG,"outLen--" + outLen[0] + "--"  + String.format("%02x", tags[j]) + "--Log读取成功：" + ByteTool.byte2hex(dataOut));
                    if (ret == 0){ //取数据成功
                        allData[0] = (byte) i;
                        int desPOs = 1 + len + (i-1)*45;
//                        LogUtil.e(TAG,  "len ="  + len +  "------j==" + j + "-------desPOs==" + desPOs);
                        System.arraycopy(dataOut,0,allData,desPOs,outLen[0]);
                        len += outLen[0];
//                        LogUtil.e(TAG,ByteTool.byte2hex(allData));
                    }
                }

            }else {
                break;
            }

        }
        List<TradeLogBean> list = parseLog(allData);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;
    }

    public int getLog(int cardType) {
        int ret = -1;
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");// 设置日期格式
        String time = df.format(new Date());
        ret = financialModule.EmvLib_SetParam(ByteTool.hexStr2Bytes(time));
        if (ret != 0) {
            deliverError(ErrorDefine.SET_TIME_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_TIME_ERR));
            return -1;
        }
        ret = setEMVParam();
        if (ret != 0) {
            deliverError(ErrorDefine.SET_EMVPARAM_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.SET_EMVPARAM_ERR));
            return -2;
        }
        byte[] tlog = new byte[1024];
        int[] num = new int[1];
        int res = -1;
        if (cardType == 0x00) {
            res = financialModule.EmvLib_GetLog((byte) 0x00, tlog, num);
        } else if (cardType == 0x02) {
            res = financialModule.EmvLib_GetLog((byte) 0x01, tlog, num);

        }
        Log.e("EmvLib_GetLog:", res + "--");
        if (res != 0) {
            deliverError(ErrorDefine.GET_LOE_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_LOE_ERR));
            return res;
        }
        List<TradeLogBean> list = parseLog(tlog);
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("data", (ArrayList<TradeLogBean>) list);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
        return res;
    }

    public void readPiccInfo() {
        Timer tm = openPicc();
        if (tm == null) {
            return;
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.PIC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.PIC_CRAD_TIMEOUT));
                        break;
                    }
                }
                byte[] cardType = new byte[2];
                byte[] serialNo = new byte[100];
                int ret = MainActivity.getmMainPicc().DLL_PiccCheck((byte) 0, cardType, serialNo);
                LogUtil.e(TAG,"开始检测非接。ret==" + ret);
                if (ret == 0) {
                    LogUtil.e(TAG,"检测非接卡成功。");
                    if (transBeforeOnline((byte) 0x02) == 0) {
                        break;
                    }
                } else if (ret == 1) {
                    LogUtil.e(TAG,"检测非接卡失败。res = 1");
//                    financialModule.PowerOff();
//                    SystemClock.sleep(1000);
//                    financialModule.PowerOn();
//                    SystemClock.sleep(3000);

//                    financialModule.EmvLib_Init();
                }

                SystemClock.sleep(300);
            }
        } finally {

//            MainActivity.getmMainPicc().DLL_PiccClose();
//            IDCReadInterface.gpio_control(46,0); //
//            IDCReadInterface.DLL_IDClose();
            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

        }


    }

    public void readIcCardInfo() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        LogUtil.e(TAG,"开始读卡");
        while (runFlag) {
            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");

                    deliverError(ErrorDefine.IC_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.IC_CRAD_TIMEOUT));
                    break;
                }
            }

            int ret = MainActivity.getmMainIcc().DLL_IccCheck((byte) 0x00);
            LogUtil.e(TAG,"检IC卡 ret =" + ret);
            if ( ret == 0) {
                LogUtil.e(TAG,"readIcCardInfo 读IC卡 检查卡成功");
                byte[] atr = new byte[20];
                int res = MainActivity.getmMainIcc().DLL_IccOpen((byte) 0, (byte) 1, atr);
                LogUtil.e(TAG,"ICC open res=" + res);
                if (res == 1) {
//                    financialModule.PowerOff();
//                    SystemClock.sleep(1000);
//                    financialModule.PowerOn();
//                    SystemClock.sleep(3000);
//
//                    financialModule.EmvLib_Init();
                    continue;
                }
                if (res != 0) {

                    continue;
                }
                if (transBeforeOnline((byte) 0x00) == 0) {

                    break;
                }

            } else  {
                LogUtil.e(TAG,"ICC检卡失败");
                continue;
            }
            SystemClock.sleep(500);
        }
        MainActivity.getmMainIcc().DLL_IccClose((byte)0);
        LogUtil.e(TAG,"DLL_IccClose");
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    /**
     *
     * @param cardType 卡类型 0--IC卡    2 非接卡
     * @return
     */
    public int transBeforeOnline(int cardType) {
        int iRet = -1;
        int TransNo = 1;
        int authorizedAmount = 0;
        int cashbackAmt = 0;

        mEmvCore = MainActivity.getEmvCore();

        iRet = addApp();

        if(iRet != 0){
            deliverError(ErrorDefine.EMV_CREATE_APP_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_CREATE_APP_ERR));
            return -1;
        }

//        iRet = addCAPubKey();
//        LogUtil.e(TAG,"addCAPubKey=" + iRet);
//        if(iRet != 0){
//            deliverError(ErrorDefine.EMV_CREATE_APP_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.EMV_CREATE_APP_ERR));
//            return -11;
//        }
        if(cardType == 0){  //接触式IC
            iRet = tranProcess(authorizedAmount,cashbackAmt);
            LogUtil.e(TAG,"tranProcess ret == " + iRet);
            if(iRet != 0){
                return iRet;
            }
        }
        if(cardType == 2){ //非接IC
            iRet = clTranProcess(authorizedAmount,cashbackAmt);
            LogUtil.e(TAG,"clTranProcess ret == " + iRet);
            if(iRet != 0){
                return iRet;
            }

        }

        if (wantTags == null)
            wantTags = new String[]{  "5A", "57", "5F20", "9F62", "9F61", "9F1F", "9F79", "9F77", "5F24", "5F34",
                    "9F26", "9F27", "9F10", "9F37", "9F36", "95", "9A", "9C", "9F02", "5F2A", "82", "9F1A", "9F03", "9F33",
                    "9F34", "9F78", "9F42"};


        int[] len = new int[1];
        byte[] dataOut = new byte[256];

        iRet = getTLV(wantTags,dataOut,len);

//        ret = financialModule.EmvLib_GetTags(wantTags, dataOut, len);
        if (iRet != 0) {
            //  resetModule();
            Log.v(TAG, "EmvLib_GetTags: ret = " + iRet);
            deliverError(ErrorDefine.GET_TAGS_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_TAGS_ERR));
            return -9;
        }

        byte[] out = new byte[len[0]];
        System.arraycopy(dataOut, 0, out, 0, len[0]);
        String returnstring = ByteTool.byte2hex(out);
        Log.e("string:", returnstring);

        int len5A = StringUtil.getTagLen(0, "5A", returnstring);
        String tag57 = StringUtil.tagParse(len5A * 2 + 4,
                "57", returnstring);
        Log.e("57", tag57 + "---");
        int len57 = StringUtil.getTagLen(len5A * 2 + 4, "57", returnstring);


        BankCardInfoBean bean = new BankCardInfoBean();

        bean.setCardType(cardType);

        bean.twoMagneticTrack = tag57;

        bean.setCardNo(getCardNo(tag57));
        bean.setICChipData(returnstring);//.substring(len5A * 2 + 8 + len57 * 2)
        Bundle bundle = new Bundle();
        bundle.putParcelable("data", bean);
        deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);

        return 0;
    }


    public int getTLV(String tags[],byte dataOut[],int tLen[]){
        int iRet = -1;
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i< tags.length; i++){

            byte byt[] = ByteTool.hexStr2Bytes(tags[i]);
//            LogUtil.e(TAG,"tags[i]" + i  + "=" +tags[i]);
            short tag = (short) (byt[0] & 0xFF);
            if(byt.length == 2){
                tag = (short) (((byt[0]&0xFF) << 8) + (byt[1]&0xFF));
            }
//            LogUtil.e(TAG,"int tag=" +tag);

            byte dOut[]  = new byte[256];
            int len[] = new int[1];
            iRet = mEmvCore.EmvLibGetTLV(tag,dOut,len);
//            Log.e(TAG,"iRet=" + iRet);
            Log.e(TAG,"iRet == " + iRet + "--" + tags[i] + "--getTLV out=" + ByteTool.bytearrayToHexString(dOut,len[0]));
            if(iRet == 0){
                sb.append(tags[i]);
                sb.append(String.format("%02x", len[0]));
                sb.append(ByteTool.bytearrayToHexString(dOut,len[0]));
            }else {
                if(tags[i].equals("9F03")){
                    sb.append(tags[i]);
                    sb.append("06000000000000");
                }else {
                    sb.append(tags[i]);
                    sb.append("00");
                }
            }
        }
        Log.e(TAG,"stringbuffer=" + sb.toString());
        byte[] tv = ByteTool.hexStr2Bytes(sb.toString());
        tLen[0] = tv.length;
        System.arraycopy(tv,0,dataOut,0,tv.length);

        return 0;
    }

    public int addApp(){
        AidList app = null;
        int iRet = -1;
        //aid1:
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41};
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x00, 0x03, 0x10, 0x10};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;


        iRet =mEmvCore.EmvLibAddApp(app);



        //aid2:
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41};
        app.mAidNameLen = 4;

        app.mAidLen = 5;
        app.mAid = new byte[]{(byte) 0xA1, 0x22 , 0x33, 0x44, 0x55};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;


        iRet =mEmvCore.EmvLibAddApp(app);

        //aid3:
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41};
        app.mAidNameLen = 4;

        app.mAidLen = 8;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x03, 0x33, 0x01, 0x01, 0x02};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x01, 0x56};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x01, 0x56};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;


        iRet =mEmvCore.EmvLibAddApp(app);

        //aid4:
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41};
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x03, 0x33, 0x01, 0x01};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x01, 0x56};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x01, 0x56};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);

        //aid5
        app = new AidList();
        app.mAidName = new byte[]{0x56, 0x49, 0x53, 0x41};
        app.mAidNameLen = 4;

        app.mAidLen = 7;
        app.mAid = new byte[]{(byte) 0xA0, 0x00 , 0x00, 0x00, 0x04, 0x10, 0x10};
        app.mPartMatch = ErrorDefine.PART_MATCH;
        app.mPriority = 0;
        app.mTargetPercent = 0;
        app.mMaxPercent = 0;
        app.mFloorLimitCheck = 1;
        app.mRandTransSel = 1;
        app.mVelocityCheck = 1;
        app.mFloorLimit = 2000;
        app.mBiasedThreshold = 0;
        app.mTACDenial = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACOnline = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mTACDefault = new byte[]{0x00, 0x00 , 0x00, 0x00, 0x00};
        app.mAcquirerId = new byte[]{0x01 ,0x23 ,0x45 ,0x67 ,(byte) 0x89 ,0x10};
        app.mDefaultDOL = new byte[]{0x03 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultDOLLen = 4;
        app.mDefaultTDOL = new byte[]{0x0F ,(byte) 0x9F ,0x02 ,0x06 ,0x5F ,0x2A ,0x02 ,(byte) 0x9A ,0x03 ,(byte) 0x9C ,0x01 ,(byte) 0x95 ,0x05 ,(byte) 0x9F ,0x37 ,0x04};
        app.mDefaultTDOLLen = 16;
        app.mAppVer = new byte[]{0x00 ,(byte) 0x96};
        app.mRiskData = new byte[]{0x01 ,0x01};
        app.mRiskDataLen = 2;

        app.mMerchantName = new byte[]{0x53, 0x48, 0x4F, 0x50, 0x31};
        app.mMerchantNameLen = 5;
        app.mMerchantCategory = new byte[]{0x12, 0x34};
        app.mMerchantID = new byte[]{0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30};
        app.mTerminalID = new byte[]{0x46 ,0x72 ,0x6F ,0x6E ,0x74 ,0x31 ,0x32 ,0x33};
        app.mCurrencyCode = new byte[]{0x08, 0x40};

        app.mCurrencyExp = 2;
        app.mRefCurrencyExp = 2;
        app.mRefCurrencyConvCode = 1000;
        app.mRefCurrencyCode = new byte[]{0x08, 0x40};

        app.mCLStatusCheck = 1;
        app.mCLFloorLimit = 100000;
        app.mCLCVMLimit = 100000;
        app.mCLTransLimit = 100000;

        iRet =mEmvCore.EmvLibAddApp(app);

        return iRet;
    }

    public int addCAPubKey(){
        int iRet = 0;
        CAPubKey capk = null;
        capk = new CAPubKey();
        capk.mRID = new byte[]{(byte) 0xA0,0x00,0x00,0x00,0x03};
        capk.mKeyID = 0x50;
        capk.mHashAlgID = 0x01;
        capk.mRsaAlgID = 0x01;
        capk.mModuleLen = (byte) 128;
        capk.mModule = new byte[]{
                (byte) 0xD1,0x11,(byte) 0x97,0x59,0x00,0x57,(byte) 0xB8,0x41,(byte) 0x96,(byte) 0xC2,(byte) 0xF4,(byte) 0xD1,0x1A,(byte) 0x8F,0x3C,0x05,
                0x40,(byte) 0x8F,0x42,0x2A,0x35,(byte) 0xD7,0x02,(byte) 0xF9,0x01,0x06,(byte) 0xEA,0x5B,0x01,(byte) 0x9B,(byte) 0xB2,(byte) 0x8A,
                (byte) 0xE6,0x07,(byte) 0xAA,(byte) 0x9C,(byte) 0xDE,(byte) 0xBC,(byte) 0xD0,(byte) 0xD8,0x1A,0x38,(byte) 0xD4,(byte) 0x8C,0x7E,(byte) 0xBB,0x00,0x62,
                (byte) 0xD2,(byte) 0x87,0x36,(byte) 0x9E,(byte) 0xC0,(byte) 0xC4,0x21,0x24,0x24,0x6A,(byte) 0xC3,0x0D,(byte) 0x80,(byte) 0xCD,0x60,0x2A,
                (byte) 0xB7,0x23,(byte) 0x8D,0x51,0x08,0x4D,(byte) 0xED,0x46,(byte) 0x98,0x16,0x2C,0x59,(byte) 0xD2,0x5E,(byte) 0xAC,0x1E,
                0x66,0x25,0x5B,0x4D,(byte) 0xB2,0x35,0x25,0x26,(byte) 0xEF,0x09,(byte) 0x82,(byte) 0xC3,(byte) 0xB8,(byte) 0xAD,0x3D,0x1C,
                (byte) 0xCE,(byte) 0x85,(byte) 0xB0,0x1D,(byte) 0xB5,0x78,(byte) 0x8E,0x75,(byte) 0xE0,(byte) 0x9F,0x44,(byte) 0xBE,0x73,0x61,0x36,0x6D,
                (byte) 0xEF,(byte) 0x9D,0x1E,0x13,0x17,(byte) 0xB0,0x5E,0x5D,0x0F,(byte) 0xF5,0x29,0x0F,(byte) 0x88,(byte) 0xA0,(byte) 0xDB,0x47
        };
        capk.mExponentLen = 3;
        capk.mExponent = new byte[]{0x01,0x00,0x01};
        capk.mExpiredDate = new byte[]{0x17,0x12,0x31};
        capk.mCheckSum = new byte[]{(byte) 0xB7,0x69,0x77,0x56,0x68,(byte) 0xCA,(byte) 0xCB,0x5D,0x22,(byte) 0xA6,0x47,(byte) 0xD1,(byte) 0xD9,(byte) 0x93,0x14,0x1E,
                (byte) 0xDA,(byte) 0xB7,0x23,0x7B};
        iRet =mEmvCore.EmvLibAddCAPubKey(capk);

        capk = new CAPubKey();
        capk.mRID = new byte[]{(byte) 0xA0,0x00,0x00,0x00,0x03};
        capk.mKeyID = 0x57;
        capk.mHashAlgID = 0x01;
        capk.mRsaAlgID = 0x01;
        capk.mModuleLen = (byte) 96;
        capk.mModule = new byte[]{
                (byte)0x94,(byte)0x2B,(byte)0x7F,(byte)0x2B,(byte)0xA5,(byte)0xEA,(byte)0x30,(byte)0x73,(byte)0x12,(byte)0xB6,(byte)0x3D,(byte)0xF7,(byte)0x7C,(byte)0x52,(byte)0x43,(byte)0x61,
                (byte)0x8A,(byte)0xCC,(byte)0x20,(byte)0x02,(byte)0xBD,(byte)0x7E,(byte)0xCB,(byte)0x74,(byte)0xD8,(byte)0x21,(byte)0xFE,(byte)0x7B,(byte)0xDC,(byte)0x78,(byte)0xBF,(byte)0x28,
                (byte)0xF4,(byte)0x9F,(byte)0x74,(byte)0x19,(byte)0x0A,(byte)0xD9,(byte)0xB2,(byte)0x3B,(byte)0x97,(byte)0x13,(byte)0xB1,(byte)0x40,(byte)0xFF,(byte)0xEC,(byte)0x1F,(byte)0xB4,
                (byte)0x29,(byte)0xD9,(byte)0x3F,(byte)0x56,(byte)0xBD,(byte)0xC7,(byte)0xAD,(byte)0xE4,(byte)0xAC,(byte)0x07,(byte)0x5D,(byte)0x75,(byte)0x53,(byte)0x2C,(byte)0x1E,(byte)0x59,
                (byte)0x0B,(byte)0x21,(byte)0x87,(byte)0x4C,(byte)0x79,(byte)0x52,(byte)0xF2,(byte)0x9B,(byte)0x8C,(byte)0x0F,(byte)0x0C,(byte)0x1C,(byte)0xE3,(byte)0xAE,(byte)0xED,(byte)0xC8,
                (byte)0xDA,(byte)0x25,(byte)0x34,(byte)0x31,(byte)0x23,(byte)0xE7,(byte)0x1D,(byte)0xCF,(byte)0x86,(byte)0xC6,(byte)0x99,(byte)0x8E,(byte)0x15,(byte)0xF7,(byte)0x56,(byte)0xE3
        };
        capk.mExponentLen = 3;
        capk.mExponent = new byte[]{0x01,0x00,0x01};
        capk.mExpiredDate = new byte[]{0x17,0x12,0x31};
        capk.mCheckSum = new byte[]{(byte)0x25,(byte)0x1A,(byte)0x5F,(byte)0x5D,(byte)0xE6,(byte)0x1C,(byte)0xF2,(byte)0x8B,(byte)0x5C,(byte)0x6E,(byte)0x2B,
                (byte)0x58,(byte)0x07,(byte)0xC0,(byte)0x64,(byte)0x4A,(byte)0x01,(byte)0xD4,(byte)0x6F,(byte)0xF5};
        iRet =mEmvCore.EmvLibAddCAPubKey(capk);

        capk = new CAPubKey();
        capk.mRID = new byte[]{(byte)0xA0,0x00,0x00,0x03,0x33};
        capk.mKeyID = (byte) 0xC0;
        capk.mHashAlgID = 0x01;
        capk.mRsaAlgID = 0x01;
        capk.mModuleLen = (byte) 144;
        capk.mModule = new byte[]{
                (byte)0xC7,(byte)0xCD,(byte)0xB6,(byte)0xF2,(byte)0xA3,(byte)0xFE,(byte)0x80,(byte)0xA8,(byte)0x83,(byte)0x4C,(byte)0xDD,(byte)0xDD,(byte)0x32,(byte)0x6E,(byte)0x10,(byte)0x82,
                (byte)0xAA,(byte)0x22,(byte)0x88,(byte)0xF4,(byte)0x7C,(byte)0x46,(byte)0x4D,(byte)0x57,(byte)0xB3,(byte)0x47,(byte)0x18,(byte)0x19,(byte)0x34,(byte)0x31,(byte)0x71,(byte)0x1A,
                (byte)0x44,(byte)0x11,(byte)0x91,(byte)0x48,(byte)0x05,(byte)0x50,(byte)0x44,(byte)0xCF,(byte)0xE3,(byte)0x31,(byte)0x37,(byte)0x08,(byte)0xBE,(byte)0xD0,(byte)0xC9,(byte)0x8E,
                (byte)0x1C,(byte)0x58,(byte)0x9B,(byte)0x0F,(byte)0x53,(byte)0xCF,(byte)0x6D,(byte)0x7E,(byte)0x82,(byte)0x9F,(byte)0xCD,(byte)0x90,(byte)0x6D,(byte)0x21,(byte)0xA9,(byte)0x0F,
                (byte)0xD4,(byte)0xCB,(byte)0x6B,(byte)0xAF,(byte)0x13,(byte)0x11,(byte)0x0C,(byte)0x46,(byte)0x85,(byte)0x10,(byte)0x7C,(byte)0x27,(byte)0xE0,(byte)0x09,(byte)0x81,(byte)0xDB,
                (byte)0x29,(byte)0xDC,(byte)0x0A,(byte)0xC1,(byte)0x86,(byte)0xE6,(byte)0xD7,(byte)0x01,(byte)0x57,(byte)0x7F,(byte)0x23,(byte)0x86,(byte)0x56,(byte)0x26,(byte)0x24,(byte)0x4E,
                (byte)0x1F,(byte)0x9B,(byte)0x2C,(byte)0xD1,(byte)0xDD,(byte)0xFC,(byte)0xB9,(byte)0xE8,(byte)0x99,(byte)0xB4,(byte)0x1F,(byte)0x50,(byte)0x84,(byte)0xD8,(byte)0xCC,(byte)0xC1,
                (byte)0x78,(byte)0xA7,(byte)0xC3,(byte)0xF4,(byte)0x54,(byte)0x6C,(byte)0xF9,(byte)0x31,(byte)0x87,(byte)0x10,(byte)0x6F,(byte)0xAB,(byte)0x05,(byte)0x5A,(byte)0x7A,(byte)0xC6,
                (byte)0x7D,(byte)0xF6,(byte)0x2E,(byte)0x77,(byte)0x8C,(byte)0xB8,(byte)0x88,(byte)0x23,(byte)0xBA,(byte)0x58,(byte)0xCF,(byte)0x75,(byte)0x46,(byte)0xC2,(byte)0xB0,(byte)0x9F
        };
        capk.mExponentLen = 3;
        capk.mExponent = new byte[]{0x01,0x00,0x01};
        capk.mExpiredDate = new byte[]{0x17,0x12,0x31};
        capk.mCheckSum = new byte[]{(byte)0x8B,(byte)0x09,(byte)0x4D,(byte)0x26,(byte)0x0B,(byte)0xDF,(byte)0x8B,(byte)0xFC,(byte)0x8B,(byte)0x9A,(byte)0x88,(byte)0xB0,(byte)0xC1,(byte)0x77,(byte)0xA4,(byte)0x3F,
                (byte)0xE2,(byte)0xFA,(byte)0xE7,(byte)0x65};
        iRet =mEmvCore.EmvLibAddCAPubKey(capk);
        return iRet;
    }

    public void resetModule() {
        financialModule.PowerOff();
        financialModule.init();
        SystemClock.sleep(3000);
        financialModule.flush();
    }

    public int AddApp() {

        byte[] AppName = new byte[33];
        byte AidLen = 0;
        byte SelFlag = 0;
        byte Priority = 0;
        byte TargetPer = 0;
        byte MaxTargetPer = 0;
        byte FloorLimitCheck = 1;
        byte RandTransSel = 1;
        byte VelocityCheck = 1;
        int FloorLimit = 2000;
        int Threshold = 0;
        byte[] TACDenial = new byte[6];
        byte[] TACOnline = new byte[6];
        byte[] TACDefault = new byte[6];
        byte[] AcquierId = new byte[7];
        byte[] dDOL = new byte[256];
        byte[] tDOL = new byte[256];
        byte[] Version = new byte[3];
        byte[] RiskManData = new byte[10];

        byte CL_bStatusCheck = 0;
        int CL_FloorLimit = 0;
        int CL_TransLimit = 0;
        int CL_CVMLimit = 0;
        byte TermQuali_byte2 = 0;


        byte[] TACDenial_1 = {(byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00};
        byte[] TACOnline_1 = {(byte) 0xD8, (byte) 0x40, (byte) 0x04, (byte) 0xF8, (byte) 0x00};
        byte[] TACDefault_1 = {(byte) 0xD8, (byte) 0x40, (byte) 0x00, (byte) 0xA8, (byte) 0x00};
        byte[] AcquierId_1 = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x12, (byte) 0x34, (byte) 0x56};
        byte[] dDOL_1 = {(byte) 0x03, (byte) 0x9F, (byte) 0x37, (byte) 0x04};
        byte[] tDOL_1 = {(byte) 0x0F, (byte) 0x9F, (byte) 0x02, (byte) 0x06, (byte) 0x5F, (byte) 0x2A, (byte) 0x02, (byte) 0x9A, (byte) 0x03, (byte) 0x9C, (byte) 0x01, (byte) 0x95, (byte) 0x05, (byte) 0x9F, (byte) 0x37, (byte) 0x04};
        byte[] Version_1 = {(byte) 0x00, (byte) 0x8c};

        System.arraycopy(TACDenial_1, 0, TACDenial, 0, TACDenial_1.length);
        System.arraycopy(TACOnline_1, 0, TACOnline, 0, TACOnline_1.length);
        System.arraycopy(TACDefault_1, 0, TACDefault, 0, TACDefault_1.length);
        System.arraycopy(AcquierId_1, 0, AcquierId, 0, AcquierId_1.length);
        System.arraycopy(dDOL_1, 0, dDOL, 0, dDOL_1.length);
        System.arraycopy(tDOL_1, 0, tDOL, 0, tDOL_1.length);
        System.arraycopy(Version_1, 0, Version, 0, Version_1.length);

        byte[] AID1 = {(byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x33, (byte) 0x01, (byte) 0x1};
        byte[] AID = new byte[17];
        System.arraycopy(AID1, 0, AID, 0, AID1.length);
        AidLen = 7;
        FloorLimitCheck = 1;

        byte[] Version1 = new byte[3];
        byte[] Version2 = {(byte) 0x00, (byte) 0x30};
        System.arraycopy(Version2, 0, Version1, 0, Version2.length);
        byte EC_bTermLimitCheck = 1;
        int EC_TermLimit = 100000;

        EMVAPPLIST PBOC_TEST_APP = new EMVAPPLIST(AppName, AID, AidLen, SelFlag,
                Priority, TargetPer, MaxTargetPer,
                FloorLimitCheck, RandTransSel, VelocityCheck,
                FloorLimit, Threshold, TACDenial,
                TACOnline, TACDefault, AcquierId, dDOL,
                tDOL, Version1, RiskManData, EC_bTermLimitCheck,
                EC_TermLimit, CL_bStatusCheck, CL_FloorLimit, CL_TransLimit,
                CL_CVMLimit, TermQuali_byte2);


        return financialModule.EmvLib_AddApp(PBOC_TEST_APP.toBytes());

    }

    /**
     * 设置EMV
     *
     * @return
     */
    public int setEMVParam() {

        EMVParam emvParam = new EMVParam();
        byte[] MerchCateCode = new byte[2];
        MerchCateCode[0] = 0x00;
        MerchCateCode[1] = 0x01;
        emvParam.setMerchCateCode(MerchCateCode);
        String MerchId = "123456789012345";
        emvParam.setMerchId(MerchId.getBytes());
        emvParam.setMerchName("EMV LIBRARY".getBytes());
        emvParam.setTermId("12345678".getBytes());
        emvParam.setTerminalType((byte) 0x22);
        emvParam.setSurportPSESel((byte) 0x01);
        byte[] Capability = {(byte) 0xE0, (byte) 0x60, (byte) 0xC8};
        emvParam.setCapability(Capability);
        byte[] ExCapability = {(byte) 0x60, (byte) 0x00, (byte) 0xF0,
                (byte) 0x20, (byte) 0x01};
        emvParam.setExCapability(ExCapability);
        byte[] CountryCode = {(byte) 0x01, (byte) 0x56};
        byte[] TransCurrCode = {(byte) 0x01, (byte) 0x56};
        byte[] ReferCurrCode = {(byte) 0x01, (byte) 0x56};
        emvParam.setCountryCode(CountryCode);
        emvParam.setTransCurrCode(TransCurrCode);
        emvParam.setTransCurrExp((byte) 0x02);
        emvParam.setReferCurrCode(CountryCode);
        emvParam.setCL_TransLimit(100000);
        emvParam.setTransType((byte) 0x00);// 交易类型
        byte[] TermTransQuali = {0x24, 0x00, 0x00, (byte) 0x80};
        emvParam.setTermTransQuali(TermTransQuali);
        emvParam.setCL_bStatusCheck((byte) 0x00);
        emvParam.setCL_CVMLimit(10000);
        emvParam.setCL_FloorLimit(20000);

        emvParam.setECTSI((byte) 0x01);
        emvParam.setEC_TermLimit(10000);
        emvParam.setEC_bTermLimitCheck((byte) 0x01);
        byte[] params = emvParam.toBytes();
        return financialModule.EmvLib_SetParam(params);

    }

    /**
     * 自动识别卡类型
     */
    public void autoReadCardNo() {

        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        res = openModule();
        Log.e(TAG, "openModule res=" + res);
        if(res==1){
            financialModule.PowerOff();
            SystemClock.sleep(1000);
            financialModule.PowerOn();
            SystemClock.sleep(3000);
            financialModule.EmvLib_Init();
            res = openModule();
        }
        Log.e(TAG, "openModule:" + res);
        try {
            while (runFlag) {
                if (timeOutMs > 0) {
                    if (tm.timeOut()) {
                        Log.e(TAG, "tm.timeOut!!");
                        deliverError(ErrorDefine.AUTO_CRAD_TIMEOUT, ErrorDefine.getErrorDescribe(ErrorDefine.AUTO_CRAD_TIMEOUT));
                        break;
                    }
                }
                SystemClock.sleep(100);
                if (financialModule.libIccCheck((byte) 0x00) == 0) {
                    if (getPan((byte) 0x00)) {
                        break;
                    }
                }
                byte[] cardtype = new byte[2];
                byte[] snbuf = new byte[20];
                if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                    if (getPan((byte) 0x01)) {
                        break;
                    }
                }
                SystemClock.sleep(150);
                if (financialModule.libMcrCheck() == 0) {
                    if (mcrRead()) {
                        break;
                    }
                }
                SystemClock.sleep(150);

            }
        }finally {

            closeModule();
            deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);
        }

    }


    /**
     * 全部打开
     *
     * @return
     */
    public int openModule() {
        int ret = -1;
//        ret = MainActivity.getMainMcr().DLL_McrOpen();
//        SystemClock.sleep(50);
        ret = MainActivity.getmMainPicc().DLL_PiccOpen();
        return ret;
    }

    /**
     * 全部关闭
     */
    public void closeModule() {

        MainActivity.getMainMcr().DLL_McrClose();
        MainActivity.getmMainIcc().DLL_IccClose((byte) 0x00);
        MainActivity.getmMainPicc().DLL_PiccClose();

    }

    /**
     * 打开非接
     *
     * @return
     */
    private Timer openPicc() {
//        int ret = IDCReadInterface.DLL_IDOpen(1); //NFC 上电
//        LogUtil.e(TAG,"PICC DLL_IDOpen ret=" + ret);
        if(Build.MODEL.equals("A108Plus")) {
            LogUtil.e(TAG,"IO转换 IDCReadInterface.gpio_control(100)");
            IDCReadInterface.gpio_control(100,0);
        }
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }

//        int res = -1;
//        byte[] atr = new byte[20];
//        for (int i = 0; i < 3; i++) {
//
//            res = MainActivity.getmMainPicc().DLL_PiccOpen();
//            LogUtil.e(TAG,"DLL_PiccOpen res =" + res);
//            if (res == 0) {
//                break;
//            } else {
//                MainActivity.getmMainPicc().DLL_PiccClose();
//            }
//        }
//        Log.e(TAG, "libPiccOpen:" + res);
//        if (res != 0) {
//            deliverError(ErrorDefine.PICC_OPEN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.PICC_OPEN_ERR));
//            return null;
//        }
        return tm;
    }


    /**
     * 打开磁头
     *
     * @return
     */
    private Timer openMsr() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
//        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        int res = -1;
        for (int i = 0; i < 3; i++) {
//            res = financialModule.libMcrOpen();
            res = MainActivity.getMainMcr().DLL_McrOpen();
            if (res == 0) {
                break;
            } else {
//                financialModule.libMcrClose();
//                financialModule.PowerOff();
//                SystemClock.sleep(1000);
//                financialModule.PowerOn();
//                SystemClock.sleep(3000);
//                financialModule.EmvLib_Init();
                MainActivity.getMainMcr().DLL_McrClose();
                MainActivity.getMainMcr().DLL_McrReset();
            }
        }
        Log.e(TAG, "LibMcrOpen:" + res);
        if (res != 0) {
            deliverError(ErrorDefine.MSR_OPEN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.MSR_OPEN_ERR));
            return null;
        }
        return tm;

    }

    public void readPiccCardNo() {
        Timer tm = openPicc();
        if (tm == null) {
            return;
        }
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.PICC_OPEN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.PICC_OPEN_ERR));
                    break;
                }
            }
            byte[] cardtype = new byte[2];
            byte[] snbuf = new byte[20];
            if (financialModule.libPiccCheck((byte) 0x41, cardtype, snbuf) == 0) {
                if (getPan((byte) 0x01)) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        financialModule.libPiccClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }


    public void readIcCardNo() {
        Timer tm = null;
        if (timeOutMs > 0) {
            tm = new Timer(timeOutMs);
            tm.start();
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.TIME_OUT, ErrorDefine.getErrorDescribe(ErrorDefine.TIME_OUT));
                    break;
                }
            }
            if (financialModule.libIccCheck((byte) 0x00) == 0) {
                if (getPan((byte) 0x00)) {
                    break;
                }

            }
            SystemClock.sleep(200);
        }
        financialModule.libIccClose((byte) 0x00);
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    /**
     * 获取主张号（卡号）
     *
     * @param cardType
     * @return
     */
    public boolean getPan(byte cardType) {

        byte[] pan = new byte[30];
        int[] len = new int[1];
        if (financialModule.EmvLib_GetPan(cardType, pan, len) == 0) {
            BankCardInfoBean bean = new BankCardInfoBean();
            if (cardType == (byte) 0x00) {
                bean.setCardType(0);
            } else {
                bean.setCardType(2);
            }
            bean.setCardNo(new String(pan, 0, len[0]));
            Bundle bundle = new Bundle();
            bundle.putParcelable("data", bean);
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            return true;
        } else {
            deliverError(ErrorDefine.GET_PAN_ERR, ErrorDefine.getErrorDescribe(ErrorDefine.GET_PAN_ERR));
            return false;
        }

    }


    public void readMsr() {
        Timer tm = openMsr();
        if (tm == null) {
            return;
        }
        deliverResult(callback, DeviceInterface.Result.START, null, isOnMain);
        while (runFlag) {

            if (timeOutMs > 0) {
                if (tm.timeOut()) {
                    Log.e(TAG, "tm.timeOut!!");
                    deliverError(ErrorDefine.MSR_CARD_TIME, ErrorDefine.getErrorDescribe(ErrorDefine.MSR_CARD_TIME));
                    break;
                }
            }
            if (MainActivity.getMainMcr().DLL_McrCheck() == 0) {

                if (mcrRead()) {
                    break;
                }
            }
            SystemClock.sleep(500);
        }
        MainActivity.getMainMcr().DLL_McrClose();
        deliverResult(callback, DeviceInterface.Result.COMPLETED, new Bundle(), isOnMain);

    }

    public boolean mcrRead() {
        byte[] track1 = new byte[200];
        byte[] track2 = new byte[200];
        byte[] track3 = new byte[200];
        byte[] len1 = new byte[1];
        byte[] len2 = new byte[1];
        byte[] len3 = new byte[1];
        int result = MainActivity.getMainMcr().DLL_McrRead(len1,track1,len2,track2,len3,track3);
        LogUtil.e(TAG,"读磁条卡result=" + result);
        if (result != 0) {
            String tk1 = new String(track1);
            String tk2 = new String(track2);
            String tk3 = new String(track3);
            LogUtil.e(TAG,"读磁条卡tk1=" + tk1);
            LogUtil.e(TAG,"读磁条卡tk2=" + tk2);
            LogUtil.e(TAG,"读磁条卡tk3=" + tk3);

            BankCardInfoBean bean = new BankCardInfoBean();
            bean.cardType = 1;
            String cardno = decodeCardNo(tk2);
            if (cardno == null) {

                deliverError(ErrorDefine.SWIPE_ERROR, ErrorDefine.getErrorDescribe(ErrorDefine.SWIPE_ERROR));
                return false;
            }
            bean.setCardNo(cardno);
            bean.oneMagneticTrack = tk1.trim();
            bean.twoMagneticTrack = tk2.trim();
            bean.threeMagneticTrack = tk3.trim();
            Bundle bundle = new Bundle();
            bundle.putParcelable("data", bean);
            deliverResult(callback, DeviceInterface.Result.SUCCEED, bundle, isOnMain);
            return true;
        } else {
            deliverError(ErrorDefine.SWIPE_ERROR, ErrorDefine.getErrorDescribe(ErrorDefine.SWIPE_ERROR));
            return false;
        }

    }

    /**
     * 从二磁道取卡号
     *
     * @param track
     * @return
     */
    public static String decodeCardNo(String track) {
        int start = 0;
        if (track != null && track.trim().length() > 0) {
            int track2_end = track.indexOf("=");
            if (track2_end == -1) {
                track2_end = track.indexOf("^");
            }
            if (track2_end == -1) {

                return "";
            }
            for (int i = 0; i < track.length(); i++) {
                if (Character.isDigit(track.charAt(i))) {
                    start = i;
                    break;
                }
            }
            String cardNo = track.substring(start, track2_end);
            return cardNo;
        }
        return null;
    }

    /**
     * 从tag57取卡号
     *
     * @param track2
     * @return
     */
    public static String getCardNo(String track2) {
        if (track2 == null)
            return null;
        int sta = 0;
        int end = track2.indexOf("D");
        if (end != -1) {
            String cardno = track2.substring(sta, end);
            return cardno;
        }
        return null;
    }

    /**
     * 生成记录
     *
     * @param log
     * @return
     */
    public static List<LoadLogBean> parseLoadLog(byte[] log) {
        int num = log[0];
        Log.e("num", num + "===");
        List<LoadLogBean> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            try {
                LoadLogBean bean = new LoadLogBean();
                byte[] tmp = new byte[6];
                System.arraycopy(log, 1 + i * 45, tmp, 0, 6);
                bean.setBeforeAmount(ByteTool.byte2hex(tmp));
                System.arraycopy(log, 1 + 6 + i * 45, tmp, 0, 6);
                bean.setAfterAmount(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + i * 45, tmp, 0, 2);
                bean.setTransNo(ByteTool.byteArray2int(tmp));
                tmp = new byte[1];
                System.arraycopy(log, 1 + 6 + 6 + 2 + i * 45, tmp, 0, 1);
                bean.setTransType(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + i * 45, tmp, 0, 2);
                bean.setCountryCode(ByteTool.byte2hex(tmp));

                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + i * 45, tmp, 0, 2);
                bean.setTransCurrCode(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + i * 45, tmp, 0, 3);
                bean.setDate(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + i * 45, tmp, 0, 3);
                bean.setTime(ByteTool.byte2hex(tmp));
                tmp = new byte[20];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + 3 + i * 45, tmp, 0, 20);
                try {
                    bean.setMerchName(new String(tmp, "gbk").trim());
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                list.add(bean);
            } catch (ArrayIndexOutOfBoundsException e) {
                break;
            }

        }
        return list;

    }

    /**
     * 生成记录
     *
     * @param log
     * @return
     */
    public static List<TradeLogBean> parseLog(byte[] log) {
        int num = log[0];
        Log.e("num", num + "===");
        List<TradeLogBean> list = new ArrayList<>();
        //标签对应数据：授权金额6，其他金额6，交易货币代码2，交易类型1，终端国家代码2，应用交易计数器 2,交易日期3，交易时间3，商户名称20，
        int[] tags = new int[]{0x9F02,0x9F03,0x5F2A,0x9C,0x9F1A,0x9F36,0x9A,0x9F21,0x9F4E,};
        int[] dlen = new int[]{6,     6,      2,    1,    2,     2 ,    3,   3,     20,    };
        for (int i = 0; i < num; i++) {
            try {
                TradeLogBean bean = new TradeLogBean();
                byte[] tmp = new byte[6];
                System.arraycopy(log, 1 + i * 45, tmp, 0, 6);
                bean.setAmount(ByteTool.byte2hex(tmp));
                System.arraycopy(log, 1 + 6 + i * 45, tmp, 0, 6);
                bean.setOtherAmount(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + i * 45, tmp, 0, 2);
                bean.setTransNo(ByteTool.byteArray2int(tmp));
                tmp = new byte[1];
                System.arraycopy(log, 1 + 6 + 6 + 2 + i * 45, tmp, 0, 1);
                bean.setTransType(ByteTool.byte2hex(tmp));
                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + i * 45, tmp, 0, 2);
                bean.setCountryCode(ByteTool.byte2hex(tmp));

                tmp = new byte[2];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + i * 45, tmp, 0, 2);
                bean.setTransCurrCode(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + i * 45, tmp, 0, 3);
                bean.setDate(ByteTool.byte2hex(tmp));

                tmp = new byte[3];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + i * 45, tmp, 0, 3);
                bean.setTime(ByteTool.byte2hex(tmp));
                tmp = new byte[20];
                System.arraycopy(log, 1 + 6 + 6 + 2 + 1 + 2 + 2 + 3 + 3 + i * 45, tmp, 0, 20);
                try {
                    bean.setMerchName(new String(tmp, "gbk").trim());
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                list.add(bean);
            } catch (ArrayIndexOutOfBoundsException e) {
                break;
            }

        }
        return list;

    }

    protected static void deliverResult(final DeviceCallback callback, DeviceInterface.Result result, Bundle bundle, boolean onMainThread) {

        DeviceInterface.deliverResult(callback, result, bundle, onMainThread);

    }

    protected void deliverError(int code, String message) {
        Bundle bundle = new Bundle();
        bundle.putInt("code", code);
        bundle.putString("message", message);
        deliverResult(this.callback, DeviceInterface.Result.ERROR, bundle, this.isOnMain);
    }


}
